home *** CD-ROM | disk | FTP | other *** search
-
- Disclaimer
-
- This user manual is shockingly short.
- The whole system should currently only be attempted by someone who is brave,
- knows either Motif or Tk, or preferably knows both.
-
- Introduction
-
- This is a binding of the Tcl language to the Motif widgets.
- Tcl is an interpreted language originally intended for use as a command
- language for other applications. It has been used for that, but has also
- become useful as a language in its own right.
-
- Tcl has been extended by a set of widgets called Tk. The Tk widgets are not
- based on the Xt Intrinsics, but are built above Xlib. They allow an easy
- way of writing X Window applications.
-
- The standard set of widgets in the X world is now the Motif set. This forms
- a large set of widgets, and these have been through a large amount of
- development over the last five years. Use of this set is sometimes a
- requirement by busineses, and other widget sets try to conform to them in
- appearance and behaviour.
-
- This system allows the programmer to use the Motif widgets instead of the
- Tk widgets from Tcl programs. This increases programmer choices, and allows
- comparison of the features of both Tcl and the Tk/Motif style of widget
- programming. The binding gives the full set of Motif widgets, accessible
- through the simple interpreted Tcl language.
-
- Acknowledgments
-
- This system is based on Tk for the style of widget programming. This was
- because it provides a good model, but it also allows the Tcl programmer to
- move relatively easily between Tk and Motif programming. An alternative
- style of binding to Motif is used in the WKSH system, which performs a
- similar sort of role for the Korn Shell. The WKSH is much closer to the C
- API for Xt than is Tk. An intermediate style is provided
- by the Wafe binding of Xt-based widgets to tcl.
-
- The documentation is incomplete (and is likely to be for a very
- long time). Consequently the programmer will probably need to refer to the
- Motif Programers Reference Manual. The system has been designed so that
- it is relatively easy to translate the C-based information in this manual
- into the corresponding Tcl information. This has been aided by the
- consistency with which Motif has been implemented in certain areas.
-
- Running Tcl/Motif programs
-
- Tcl/Motif programs may be run by the `moat' (MOtif And Tcl) interpreter.
- When called with no arguments it reads Tcl commands from standard input.
- When called by
-
- moat file-name
-
- it reads Tcl commands from `file-name', executes them and then enters the
- Tm event loop. This is similar to the Tk `wish' and the concept was
- borrowed from there. However, it does not use the wish prefix of ``-file''
- but instead the standard form from ``tclsh''.
-
- Depending on your shell interpreter, you will probably be able to run
- Tcl/Motif programs as standalone programs. If your moat interpreter is
- installed in say `/usr/local/bin/moat', make this the first line of your
- executable program:
-
- #!/usr/local/bin/moat
-
- Widget naming
-
- Widgets are visual objects that exist on the screen.
- They are organised as a hierarchy, with the application itself forming the
- root of this hierarchy.
- The naming of objects within this hierarchy is similar to the ``absolute
- path names'' of Unix files with a `.' replacing the `/' of Unix.
- The application itself is known as `.'.
- A Form in the application may be known as `.form1'.
- A Label in this form may be `.form1.okLabel', and so on.
- Note that Xt requires that `.' can only have one child
- (except for dialogs).
- This naming convention is the same as in Tk.
-
- Widget creation
-
- Widgets belong to classes, such as Label, PushButton or List.
- For each class there is a creation command which takes the pathName of the
- object as first argument with optional further arguments:
-
- xmForm .form1
-
- xmLabel .form1.okLabel
-
- xmLabel .form1.cancelLabel -labelString "Get rid of me"
-
- creates a Form `form1' as child of `.', and two Labels `okLabel' and
- `cancelLabel' as children of `form1'. The `cancelLabel' has additional
- arguments that set the labelString to "Get rid of me".
-
- The set of classes generally mirrors the Motif set.
- Some widgets in Motif and Xt are not accessible from this binding because
- they are intended for use in inheritance only, such as Core and Primitive.
- The types of widgets that can be created using this include the primitive
- widgets:
-
- xmArrowButton - a simple arrow,
- xmDrawnButton - a button with graphics in it
- xmCascadeButton - for use in menus
- xmToggleButton - for on/off boxes
- xmLabel - a fixed piece of text
- xmText - a text editor
- xmTextField - a one line text editor
- xmSeparator - for simple lines between objects
- xmList - a list selector
- xmScrollBar - a horizontal or vertical scrolling bar
-
- and the Manager widgets:
-
- xmBulletinBoard - simple geometry management
- xmRowColumn - regular geometry management
- xmPanedWindow - multiple panes separated by sashes
- xmFrame - a 3-D border
- xmScale - a slider on a scale
- xmScrolledWindow - for displaying a clip view over an area
- xmMainWindow - contains a menu bar and the main application windows
- xmForm - for irregular geometry arrangements
- xmMessageBox - message display area
- xmCommand - a command entry area with a history list
- xmFileSelectionBox - selection of a file from a list
-
- Motif has two special commands for creating a ScrolledList and a ScrolledText.
- These commands actually create a pair of widgets: a List or Text inside a
- ScrolledWindow. To create such widgets is similar to the C binding: the
- List (or Text) widget name is given. If the parent ScrolledWindow is required
- then you have to call the ``parent'' method on the List or Text widget.
-
- xmForm .form1
-
- xmScrolledList .form1.list2
-
- [.form1.list2 parent] setValues -attachTop attach_form
-
- Motif also has convenience functions that create dialogs.
- These don't create ordinary widgets, but Motif pretends that they do.
- Tm follows this, and allows you to use commands such as
-
- xmQuestionDialog .askMe
-
- to create such dialogs. When you have to destroy such widgets, destroy the
- parent:
-
- [.askMe parent] destroy
-
- This set of dialogs includes:
-
- xmBulletinBoardDialog - a dialog with arbitrary contents, based on bulletinBoard
- xmFileSelectionDialog - a dialog based on fileSelectionBox
- xmFormDialog - a dialog based on form
- xmInformationDialog - a dialog displaying information
- xmMessageDialog - a dialog showing a message
- xmPromptDialog - a dialog with a prompt area
- xmQuestionDialog - a dialog asking a question
- xmSelectionBoxDialog - a dialog based on selectionBox
- xmWarningDialog - a dialog showing a warning message
- xmWorkingDialog - a dialog showing a busy working message
-
- For example, consider a rowColumn containing two labels and a pushButton,
- where the rowColumn is inside a mainWindow:
-
- xmMainWindow .main
- xmRowColumn .main.rowcol
- xmLabel .main.rowcol.label1
- xmLabel .main.rowcol.label2
- xmPushButton .main.rowcol.btn
-
- Not all objects used in the OSF C library are supported: gadgets are
- not supported by Tm, nor are the ``simple'' menu functions.
-
- Managing widgets
-
- Before a widget cn be displayed, it must be brought under the geometry
- control of its parent (similar to placing a Tk widget). This can be done
- by the ``manageChild'' method of each widget, but also by an optional
- third command to each widget creation function, similar to the
- XtCreateManagedWidget functions. For example,
-
- xmLabel .l1 managed
- xmLabel .l2
- .l2 manageChild
-
- Documentation
-
- The widgets described above not only look and act the same as the Motif
- widgets, they *are* the Motif widgets. So descriptions of them in any Motif
- book or reference apply. In the Motif Programmers Reference these widgets
- are described under the same names, prefixed by ``Xm'' as in XmPushButton.
- The creation functions are prefixed by ``XmCreate'' as in
- XmCreatePushButton.
-
- The Tm documentation is at present incomplete. There should be a man page
- for each widget, under the name of the widget prefixed by ``Tm'' as in
- TmPushButton.
-
- Widget commands
-
- Creating a widget actually creates a Tcl command known by its pathName.
- This command may be executed with at least one parameter
- to either change the behavior of the object
- or the value of its components, or to get information about the object.
- The parameter acts like a ``method'' to the object, and specifies an action
- that it should perform. The parameters that are recognised by every object
- include:
-
- unmanageChild - remove the object from its parents geometry management, which
- makes it disappear from the display
-
- manageChild - bring it back under geometry management and make it appear again
-
- mapWidget - remain under geometry management, but make it disappear
-
- unmapWidget - make it reappear
-
- realizeWidget - create windows for the widget and its children (usually used only by ``.'')
-
- getValues - obtain properties of the widget
-
- setValues - set properties of the widget
-
- parent - return the parent of the widget
-
- destroyWidget - destroy the widget and all its children
-
- setSensitive - change the sensitivity of the widget to responses to input
-
- callActionProc - call an action procedure (usually used in regression testing)
-
- dragStart - used in drag and drop
-
- dropSiteRegister - used in drag and drop
-
- getGC - return a graphics context (used for drawing in DrawingArea and DrawnButton)
-
- any string ending in ``Callback'' - register Tcl code to be executed when
- something happens to the widget.
-
- For example,
-
- .form1.okLabel unmanageChild
-
- .form1.okButton activateCallback {puts stdout "I was pushed into it..."}
-
- Unmanaging a widget removes it from the display, and from the geometry
- management of its parent. Managing it reverses this. The other methods
- are explained later.
-
- Other widget commands
-
- The root widget ``.'' has a number of commands unique to it. Generally,
- these are commands that use the application context (moat only uses one
- application context). These commands include
-
- addInput
- removeInput
- mainLoop
-
- Both Text and List have a large number of other commands due to the
- complexity of these widgets. Other widgets also have special methods.
- See the manual pages for further information.
-
- Widget resources
-
- Each widget has a set of resources that can be set at creation time,
- set at a later time, or queried for their value. For example, a pushButton
- has a width and a height, a labelString that is the text that will show in
- it, a foreground and background colour, a fontList giving the set of fonts
- that will be used to draw the text, and so on.
-
- All resource names are prefixed by a minus `-' in Tcl programs, for
- consistency with the Tk widgets.
- On setting a value, all resources take the next
- word as value, and on getting a value the next word is the name of a variable
- to store the value in.
-
- On creation, the resource/value pairs come after the widget pathName, as in
-
- xmLabel .okLabel -labelType pixmap -labelPixmap xlogo32
-
- which sets the labelType to pixmap and the labelPixmap to xlogo32.
-
- Resources can be set at any time using the setValues method
-
- .text setValues -editMode editable -value "Some text"
-
- which ensures that the text widget can be edited, and sets a
- value of "Some text".
-
- Resources can be obtained from the widget using the getValues method.
- For example
-
- .fileSelectionBox getValues -dirSpec file_selected -directory dir
-
- stores in the Tcl variable file_selected the filename that was entered, and
- in the Tcl variable dir the directory in which the file selection occurred.
-
- Each widget inherits resources from superclasses. For example, Label is a
- subclass of Primitive which in turn is a subclass of Core. From Core it
- inherits resources such as background, height and width. From Primitive it
- inherits resources such as foreground. It is neccessary to look at these
- superclasses. In addition, each class adds extra resources. For example,
- Label has the additional resources labelType, labelPixmap and labelString,
- among others.
-
- Resources are documented in the Tm man page for each widget. This
- documentation is weak.
-
- Resource names can be obtained from the Motif documentation for each
- widget. The Motif documentation for each widget has a set of tables
- headed ``Resource Set''. In the table of resources, the names of these
- are given prefixed by ``XmN'', such as XmNeditMode. Drop the prefix
- to get the Tcl resource name. Case is important here.
-
- Resource values can also be obtained from the Motif documentation. For
- each resource look at its type. Types such as Dimension and Position are
- numeric types, and along with int types need an integer value. In the Tcl
- program they are implemented as Tcl Strings, as is everything. In fact,
- all resource values are Tcl strings. Pixmaps, for example, are the string
- name of a pixmap such as ``xlogo32''. Pixel is a color such as ``blue'',
- or a hexadecimal representation of the color. Types such as the
- arrowDirection of an ArrowButton form a discrete set with values listed as
- XmARROW_UP, XmARROW_DOWN, etc. For these types, drop the ``Xm'' and use
- the rest of the string as the value. On setting values, case is not
- important but on getting values the string will be lower case for these
- discrete types.
-
- So for example, a pushButton may have
-
- xmPushButton .btn -width 100
- .btn setValues -labelString "Push Me" -foreground red
- .btn getValues -background bg
- puts stdout "background colour is $bg"
-
- Callbacks
-
- When the user does things to a widget, it may cause the widget to take certain
- actions. For example, when a button is pressed it changes appearance to
- look pressed in. Some of these actions can have Tcl code attached to them,
- so that the Tcl code is evaluated when the action is performed. The Tcl
- code is attached to a ``callback'' by a widget command. For example, a
- pushButton has an activateCallback that is called when the user presses and
- releases the left mouse button inside the widget; it has an armCallback
- that is called when the user presses the mouse button; it has a
- disarmCallback that is called when the user releases the mouse button
- inside the widget.
-
- Tcl code is attached to a callback by giving it as the second argument to the
- appropriate widget methodod. For example,
-
- .btn armCallback {puts stdout "Stop squashing me!!!"}
- .btn disarmCallback {puts stdout "That's better!"}
-
- The names of the callbacks available for a particular widget are derived
- from the resource documentation for the Motif widget. Each callback ends
- with the string "Callback" in its name. Drop the "XmN" from the Motif
- description to gain the widget command. Callbacks are treated differently
- to other resources because the Xt toolkit treats them differently - the
- resource is not meant to be handled directly by any ordinary application.
-
- Callback substitutions
-
- Motif supplies information to each callback function that is specific to
- the widget type. Generally this is not of much interest. However, for some
- widgets such as List this is used to supply important information, such as
- what item in the List was selected! To make this available to the Tcl
- callback function a pattern substitution mechanism may be used. Any ``%''
- followed by a word will be treated as a pattern for potential substitution.
- For example, ``%item'' in a List will be replaced by the item selected,and
- ``%item_position'' will be replaced by its position in the list.
- An example list callback is
-
- .list singleSelectionCallback {print_info %item %item_position}
-
- proc print_info {item position} {
-
- puts stdout "item was $item, at position $position"
-
- }
-
- The substitutions allowed may be found from the Motif documentation. In
- the description of callback information one or more structures will be
- defined. The field names in these structures are the names used in ``%''
- substitutions. Not all of the possibilities are implemented yet.
- This is admittedly obscure and not easy to find, so the Tm
- documentation needs to fix this lack. If you feel upto reading C code
- instead, the upto date ``list'' is found in the file ``tmExpand.c''
-
- Text verify callbacks
-
- The Text widget allows special processing by the application of text entered.
- After a character has been typed, or text pasted in, initial processing by
- the Text widget determines what the user is entering. This text is then
- passed to special callback functions. These functions can make copies of
- the text, can alter it, or can set a flag to say do not display it. Simple
- uses for this are a password entry widget that reads the text but does not
- display it (or echoes `*' instead), or text formatting widgets.
-
- The callback mechanism for this is basically the same as for other
- callbacks, and similar sorts of substitutions are allowed. For example, the
- term %currInsert is replaced by the current insertion position. Other
- substitutions do not give a value, but rather give the name of a tcl
- variable. This allows the application to change the value as required. The tcl
- variable is in the context of the callback caller, so upvar should be used. For
- example, to turn off echoing of characters, the following should be done:
-
- .text modifyVerifyCallback {no_echo %doit}
-
- proc no_echo {doit} {
- upvar 1 $doit do_insert
-
- set do_insert false
- }
-
- (Actually, the tcl variable here is the global variable _Tm_Text_Doit. For
- this reason, variables beginning with _Tm_ are reserved for use by the Tm
- library.)
-
- Other substitutions that can be made in the modifyVerify callback are ``ptr''
- and ``length''. ptr is the string that is being entered, and length is its
- length. These may be changed by the callback procedure. For example, to
- change all incoming text to uppercase,
-
- proc allcaps {ptr length} {
- upvar 1 $ptr p
- upvar 1 $length l
-
- if {$l == 0} return
- set upper [string toupper $p]
- set p $upper
- }
-
- .text modifyVerifyCallback {allcaps %ptr %length}
-
- Dialogs
-
- Selection Box has a number of component children, which may be managed or unmanaged
- by the application. If the SelectionBox was named .sel, these are
-
- .sel.Items
- .sel.ItemsList
- .sel.Selection
- .sel.Text
- .sel.Separator
- .sel.Apply
- .sel.Cancel
- .sel.Help
- .sel.OK
-
- The same applies to Message Box. These widgets are often managed or unmanaged
- to add or remove elements from a dialog. Motif gives no information about
- types of these widgets, so managing and unmanaging are really the only two
- operations that you should perform on these widgets.
-
- Actions
-
- Actions may be added to a widget in a similar way to the C version. In that
- you define an action in a translation table which is set in the widget. You
- then have to register the action with the toolkit so that it is attached to
- a C function. In this binding, the tcl code is placed as the arguments to the
- action in the translation table. Regisitering the action links a generic action
- handler which in turn will handle the tcl code. Here is what it looks like to
- add action to make an arrow turn left or right when `l' or `r' is pressed:
-
- xmArrowButton .arrow managed
-
- .arrow setValues -translations \
- "<Key>r: exec(arrow_direction %w arrow_right) \n\
- <Key>l: exec(\"arrow_direction %w arrow_left\")"
-
- proc arrow_direction {arrow direction} {
- puts stdout "Changing direction to $direction"
- $arrow setValues -arrowDirection $direction
- }
-
- The pattern %w is substituted for the name of the tcl widget. More
- substitutions may be added in later (eg for x, y).
-
- The method callActionProc is available for every widget. The purpose of this
- is to allow regresion tests to be performed. This takes an action as further
- parameter, using the usual Xt syntax. For example, to simulate the return key
- press occurring within an arrow button, call the ArmAndActivate() action:
-
- .arrow callActionProc ArmAndActivate()
-
- This sends (by default) a ClientMessage event to the widget. Most widgets
- ignore the event for most events, so this is sufficient. Some actions
- require event detail, though. For example, when a mouse button release occurs,
- the widget checks to see if the release occurred *inside* or *outside* the
- widget. It does this because if the event occurs inside, then the callbacks
- attached to the Activate() action are invoked, but otherwise they are not.
- To handle this, an event of type ButtonPress, ButtonRelease, KeyPress or
- KeyRelease can be prepared with some fields set. For example, a ButtonRelease
- occurring within the arrow can be sent by
-
- .arrow callActionProc Activate() \
- -type ButtonPress \
- -x 0 -y 0
-
- Some of the Text manipulation actions require a KeyPress event, such as
- self-insert(), which inserts the character pressed. The character is
- actually encoded as a keycode, which is a hardware dependant code, too
- low-level for this binding. To prepare such an event, this toolkit uses
- *keysyms* which are abstractions for each type of key symbol. The alphanumerics
- have simple representations as themselves (`a', `A', `2', etc). Others have
- symbolic names (`space', `Tab', `BackSpace', etc). These are derived from
- the X Reference manual or in the file <X11/keysymdefs.h> by removing the
- prefix ``XK_''.
-
- For example, to insert the three characters `A a' into .text
-
- .text callActionProc self-insert() \
- -type KeyPress \
- -keysym A
- .text callActionProc self-insert() \
- -type KeyPress \
- -keysym space
- .text callActionProc self-insert() \
- -type KeyPress \
- -keysym a
-
-
- The set of actions that require this level of preparation of the X event
- is nowhere documented explicitly. You have to read between the lines of
- the Motif documentation, or guess at behaviour (or read Motif source code).
-
- The Motif world
-
- In earlier versions than 0.8, a specialised interpreter was used, much like
- Tk's ``wish''. To conform to the new extension methods of tcl7.0, this was
- changed. Part of the result of this is that the Xt world has to be explicitly
- brought into existence. This also allows the class and fallback resources to
- be set, and leaves hooks for things like setting the application icon
- to be added later to this binding.
-
- The three world manipulation functions added are
-
- xtAppInitialize
- . realizeWidget
- . mainLoop
-
- xtAppInitialize may take parameters of -class and -fallback_resources. If
- the class option is omitted, the binding will deduce a class by capitalising
- the first letter of the application name, and - if it was an `x' - also
- capitalising the second letter.
-
- Examples
-
- A number of examples are in the programs directory. Those with `DH' in
- them duplicate the examples in Dan Heller's ``Motif Programming Manual'',
- O'Reilly & Associates Inc. Those that are just numbered are undocumented
- test programs. They may not behave in a nice way, but that doesn't matter
- too much.
-
- The following example is in the programs directory as progEG.
- The typical structure of a Motif program is that the top-level object is a
- mainWindow. This holds a menu bar, and a container object such as a form or
- a rowColumn which in turn holds the rest of the application objects. So a
- mainWindow with a list and some buttons in a form would be created by
-
- xtAppInitialize -class Example
-
- xmMainWindow .main
- xmForm .main.form
- xmList .main.form.list
- xmPushButton .main.form.btn1
- xmPushButton .main.form.btn2
-
- The form acts as what is called the ``workWindow'' of the mainWindow. This
- resource would be set by
-
- .main setValues -workWindow .main.form
-
- Values would also be set into the list and buttons:
-
- .main.form.list setValues \
- -itemCount 3 \
- -items "one, two, three" \
- -selectionPolicy single_select
- .main.form.btn1 setValues -labelString Quit
- .main.form.btn2 setValues -labelString "Do nothing"
-
- Behaviour would be set by a callback function
-
- .main.form.btn1 activateCallback {exit 0}
- .main.form.list singleSelectionCallback {puts stdout "Selected %item"}
-
- Geometry would be set for the form, to put the objects in their correct
- relation to each other. Suppose this is the list on the left, with the two
- buttons one under the other on the right:
-
- .main.form.list setValues \
- -topAttachment attach_form \
- -leftAttachment attach_form \
- -bottomAttachment attach_form
- .main.form.btn1 setValues \
- -topAttachment attach_form \
- -leftAttachment attach_widget \
- -leftWidget .main.form.list
- .main.form.btn2 setValues \
- -topAttachment attach_widget \
- -topWidget .main.form.btn1 \
- -leftAttachment attach_widget \
- -leftWidget .main.form.list \
-
- Finally, windows are created and the main event loop is entered:
-
- . realizeWidget
- . mainLoop
-
- Drag and Drop
-
- Drag and drop was introduced into Motif 1.2. It is complicated. We shall
- first look at the drop side. A widget has to first register itself as a
- drop site, so that when an attempt is made to drop something on it, it will
- try to handle it. This registration is done by the widget method
- dropSiteRegister. This registration must include tcl code to be executed
- when a drop is attempted, and this is done using the resource dropProc. The
- first part of what makes D&D hard is that you have potentially two
- different applications attempting to communicate, one dropping and the
- other accepting the drop. A protocol is needed between these, so that they
- share a common language. This is done in registration by saying what types
- of protocol are used, and how many there are. This is done using X atoms,
- and the major ones are COMPOUND_TEXT, TEXT and STRING. Thus registration is
- done, for example, by
-
- .l dropSiteRegister \
- -dropProc {startDrop %dragContext} \
- -numImportTargets 1 \
- -importTargets COMPOUND_TEXT
-
- This allows .l to be used as a drop site, accepting COMPOUND_TEXT only.
- Multiple types are allowed, using the Motif list structure of elements
- separated by commas as in "COMPOUND_TEXT, TEXT, STRING".
- When a drop occurs, the procedure startDrop is called, with one substituted
- parameter. This parameter is a dragContext, which is a widget created to
- by Motif to handle the drag part of all this. You must include this
- parameter, or the next stage doesn't get off the ground.
-
- When a drag actually occurs, Motif creates a dragContext widget. A drag is
- started by holding down the middle button in a drag source, which is
- discussed later. The dragContext widget contains information about the drag
- source, which is to be matched up against where the drop occurs. When the
- drop occurs, by releasing the middle button, the tcl code registered as
- dropProc is executed. This should have the dragContext widget as parameter.
- This code may try to determine if the drop should go ahead, but more
- normally will just act as a channel through to the actual information
- transfer. Still here? Good. The dragProc doesn't actually do the
- information transfer, it just determines whether or not it is possible, and
- if it is, what protocols should be used, and how.
-
- The drop receiver may decide that it wants something encoded as TEXT,
- followed by something encoded as COMPOUND_TEXT, and then by something in
- STRING format (beats me why, though...). it signals this by a (Tcl) list of
- dropTransfer pairs, consisting of the protocol (as an X atom name) and the
- widget that is being dropped on. Huh? Why the widget that is being dropped
- on? Because when a drop on a widget takes place, this is actually dealt
- with by the dragContext widget, and this is about to hand the transfer over
- to a transferWidget. Yes, I know you are using Tcl because you couldn't
- handle triple indirections (or rather, don't want too!), but they occur
- anyway... So here is a simple dragProc:
-
- proc startDrop {dragContext} {
- $dragContext dropTransferStart \
- -dropTransfers {{COMPOUND_TEXT .l}} \
- -numDropTransfers 1 \
- -transferProc {doTransfer %closure {%value}}
- }
-
- The dragContext widget uses the command dropTransferStart to signal the
- beginning of the information transfer (it could also signal that the drop
- is to terminate, with no information transfer). It will accept one chunk of
- information in the COMPOUND_TEXT format, and pass this on to the .l widget.
- The information transfer is actually carried on by the Tcl procedure in the
- transferProc resource. The only formats currently accepted (because they
- are hard-coded into Tm) are COMPOUND_TEXT, TEXT and STRING.
-
- The transferProc resource is a function that is called when the drop
- receiver actually gets the information dropped on it. This should take at
- least two parameters. The %value is substituted for the actual information
- dropped on it, and %closure is the second element in the dropTransfer list
- which should be the widget the drop is happening on. (Why not let Tm
- determine this? I dunno. Consistency with Motif doco? Brain damage late at
- night?) Then the dropped on widget can take suitable action. This function
- resets the label to the text dropped on it:
-
- proc doTransfer {destination value} {
- $destination setValues -labelString $value
- }
-
- where destination is substituted by %closure and value by %value.
-
- Send
-
- Tk has a primitive called ``send''. In this, each interpreter has a name,
- and you can send tcl commands from one interpreter to another. When an
- interpreter receives a sent command it executes it, and returns any result
- back to the original interpreter. This mechanism is also available to
- tm, so that Motif applications can set commands to other Motif applications,
- and also to and from Tk ones.
-
- If a tm application succeeds in registering its name,
- from then on, it can send to another. For example,
-
- send interp2 {puts stdout "hello there"}
-
- instructs ``interp2'' to display a message.
-
- Automated testing
-
- Tcl uses an automated test system that can run regression tests on a system.
- it does so by ``sourcing'' a file containing a set of test procedures,
- including a procedure called ``test''. This takes 4 arguments: the first is
- the name of the test, the second is a textual description of the test, the
- third is the code to execute to perform the test, and the last is the
- expected result. The ``test'' procedure runs the test and if the actual
- result differs from the expected one, an error message is printed.
-
- This mechanism is used well for the tcl core. It is also used for Tk, but
- with less success: while good for batch mode testing, it does not handle
- the interactive nature of GUI environments. To perform batch mode testing
- in such environments, one needs to be able to create input events to
- simulate an interactive user.
-
- One approach is to create raw X events and to feed them directly into the
- Xt event loop handler. This requires a very low-level knowledge of what is
- going on, and anyway does not reflect the object structure of the Xt
- toolkit. Each widget defines a set of ``actions'' that are intended to be
- the ``public'' interface of that widget. This is the hook that the tclMotif
- test procedures use to extend the tcl testing into this GUI environment.
-
- A command for any widget is ``callActionProc''. This takes an argument
- which is the name of the action for the widget. For example, a button has
- an Arm action, so this can be invoked by
-
- .btn callActionProc Arm
-
- This will perform the visual behaviour for this action, and also call any
- callbacks associated with this action.
-
- In an ideal world, this would be enough. Some parts of Motif are not quite
- ideal yet. For example, the Activate action is, by default, invoked by
- releasing the mouse button after it has been pressed within a PushButton.
- The association between user action and widget action is controllable
- through the translation tables for that widget, so these could be - to be
- bizarre - set up so that pressing d (for down) arms the button, while
- pressing u (for u) activates it. Motif (at 1.2.1 anyway) refuses to admit
- this possibility and is hard-coded to assume that the action came from a
- ButtonRelease. The reason is simple: if the release occurs within the
- PushButton, it means that the action was desired; if it occurs outside the
- PushButton then the user has cancelled the action by moving out of the
- widget. So it has to be a mouse event for this model to be followed.
-
- For tests, this means that you cannot just issue an Activate action. You do
- have to prepare an X button event to the extent of setting the x and y
- coordinates so that the internal Motif function can determine whether or
- not to invoke the callbacks. This looks like:
-
- .btn callActionProc Activate \
- -type ButtonPress \
- -x 0 -y 0
-
- to be within the widget, or
-
- .btn getValues -width w -height h
- set big_h [expr {2 * $h}]
- set big_w [expr {2 * $w}]
- .btn callActionProc Activate \
- -type ButtonPress \
- -x $big_w -y $big_h
-
- to be outside the widget.
-
-